#include "camera_capture.h"
#include "rtc_base/thread.h"
#include <modules/desktop_capture/desktop_capture_options.h>
#include <QDebug>
#include <iostream>
#include "easylog.h"

CameraCapturer::CameraCapturer() {

}

void CameraCapturer::startCapturer() {
  auto options = webrtc::DesktopCaptureOptions::CreateDefault();
  options.set_allow_directx_capturer(true);
  capturer_ = webrtc::DesktopCapturer::CreateScreenCapturer(options);
  capturer_->Start(this);
  CaptureFrame();
}

webrtc::MediaSourceInterface::SourceState CameraCapturer::state() const {
  return webrtc::MediaSourceInterface::kLive;
}

bool CameraCapturer::remote() const {
  return false;
}

bool CameraCapturer::is_screencast() const {
  return true;
}

absl::optional<bool> CameraCapturer::needs_denoising() const {
  return false;
}

static void RawToBmp(unsigned char *pRawImage, int ImageHeight, int ImageWidth, int bitcount,std::string filePath)
{

    unsigned char *imgData;
    LONGLONG dataSizePerLine = ((ImageWidth * bitcount + 31) >> 5) << 2;


    int plaLen = bitcount <= 8 ? 2 << (bitcount - 1) : 0;
    std::cout << "plaLen = " << plaLen << endl;
    int headerLength = 14 + 40 + plaLen * 4;
    LONGLONG dataLength = dataSizePerLine*(ImageHeight - 1) + ImageWidth*bitcount / 8;
    std::cout << "headerLength = " << headerLength << endl;
    std::cout << "dataLength = " << dataLength << endl;
    short int biPlanes = 1;
    char bm[2] = { 'B', 'M' };
    long bfReserved1 = 0;
    LONGLONG bfSize = headerLength + dataLength;
    long biHeight = ImageHeight*(-1);
    long bfOffBits = headerLength;
    long bisize = 40;
    long biCompression = 0; LONGLONG biSizeImage = dataLength;
    long biXPelsPerMeter = 0, biYPelsPerMeter = 0;
    long biClrUsed = plaLen; int biClrImportant = 0;
    imgData = new unsigned char[headerLength + dataLength];
    memset(imgData, 0, headerLength + dataLength);
    memcpy(imgData, &bm, 2);
    memcpy(imgData + 2, &bfSize, 4);
    memcpy(imgData + 6, &bfReserved1, 4);
    memcpy(imgData + 10, &bfOffBits, 4);
    memcpy(imgData + 14, &bisize, 4);
    memcpy(imgData + 18, &ImageWidth, 4);
    memcpy(imgData + 22, &biHeight, 4);
    memcpy(imgData + 26, &biPlanes, 2);
    memcpy(imgData + 28, &bitcount, 2);
    memcpy(imgData + 30, &biCompression, 4);
    memcpy(imgData + 34, &biSizeImage, 4);
    memcpy(imgData + 38, &biXPelsPerMeter, 4);
    memcpy(imgData + 42, &biYPelsPerMeter, 4);
    memcpy(imgData + 46, &biClrUsed, 4);
    memcpy(imgData + 50, &biCompression, 4);

    if (headerLength > 54) {
        if (bitcount == 1) {
            for (char i = 0; i < 2; i++) {
                char gray[4] = { char(i * 255), char(i * 255), char(i * 255), char(255) };
                memcpy(imgData + 54 + 4 * i, gray, 4);
            }
        }
        else if (bitcount == 4) {
            for (char i = 0; i < 16; i++) {
                char gray[4] = { char(i * 17), char(i * 17), char(i * 17), char(255) };
                memcpy(imgData + 54 + 4 * i, gray, 4);
            }
        }
        else  if (bitcount == 8) {
            for (int i = 0; i < 255; i++) {
                char gray[4] = { char(i), char(i), char(i), char(255)};
                memcpy(imgData + 54 + 4 * i, gray, 4);
            }
        }
    }
    int dw = ImageWidth*bitcount / 8;
    for (int i = 0; i < ImageHeight; i++)
    {
        memcpy(imgData + headerLength + dataSizePerLine*i, pRawImage + dw*i, dw);
    }

    FILE *fp_bmp;
    fp_bmp = fopen(filePath.c_str()/*"temp.bmp"*/, "wb");
    fwrite((void*)imgData, bfSize, 1, fp_bmp);
    fclose(fp_bmp);
}

void CameraCapturer::OnCaptureResult(webrtc::DesktopCapturer::Result result,
                                 std::unique_ptr<webrtc::DesktopFrame> frame) {
    if (result != webrtc::DesktopCapturer::Result::SUCCESS)
        return;
    int width = frame->size().width();
    int height = frame->size().height();
    if (!i420_buffer_.get() ||
        i420_buffer_->width() * i420_buffer_->height() < width * height) {
        i420_buffer_ = webrtc::I420Buffer::Create(width, height);
    }
    libyuv::ConvertToI420(frame->data(), 0, i420_buffer_->MutableDataY(),
        i420_buffer_->StrideY(), i420_buffer_->MutableDataU(),
        i420_buffer_->StrideU(), i420_buffer_->MutableDataV(),
        i420_buffer_->StrideV(), 0, 0, width, height, width,
        height, libyuv::kRotate0, libyuv::FOURCC_ARGB);
    OnFrame(webrtc::VideoFrame(i420_buffer_, 0, 0, webrtc::kVideoRotation_0));
}

void CameraCapturer::OnMessage(rtc::Message* msg) {
  if (msg->message_id == 0)
    CaptureFrame();
}

void CameraCapturer::CaptureFrame() {
  capturer_->CaptureFrame();

  rtc::Location loc(__FUNCTION__, __FILE__,__LINE__);
  rtc::Thread::Current()->PostDelayed(loc, 33, this, 0);
}
